#ifndef RMD_LANE_DETECTION_H_
#define RMD_LANE_DETECTION_H_

#include "data_frame.h"
#include "lane_feature_extraction_v0.h"
#include "lane_model_fitting.h"

namespace rmd {

class AutoCluster
{
  public:
    short index = -1;
    short cluster = -1;
    short visited = 0;
    cv::Point point;
    int   pts = 0;//points in MinPts
    int   point_type = 1; //1 noise 2 border 3 core
    float sum_value = 0;
    float avg_value = kUnknowValue;
    std::vector<int> corepts;
     AutoCluster (){}
    AutoCluster (int id,float a,float b,int c){
            index = id;
            point.x = a;
            point.y = b;
            cluster = c;
    }
};

class LaneDetection {
 public:
  LaneDetection();
  virtual ~LaneDetection();

  std::vector<LaneResult> Update(DataFrame* data_frame, std::vector<cv::Rect>& vecicle_info);

 private:
  DataFrame* data_frame_;

  int process_image_width;
  int process_image_height;
  short end_line_;
  short middle_start_line_;
  short far_line_;
  short start_line_;

  float refine_lane_width_;
  cv::Point m_user_setVP;
  short off_x_length;
  short off_y_length;

  std::vector<LaneResult> select_lane_lines;

  cv::Mat process_image_;
  std::vector<cv::Rect> vehicle_info_;

  LaneFeatureExtraction* lane_feature_extraction_;
  LaneModelFitting* lane_modefit_;

  short const_roi_continue;

  int single_line_continue ;
  CurrentShowLine current_show_lines;
  std::vector<INITLDVP> save_good_vps;

  void ClassInitalization();
  void SetDataFrameToClass(DataFrame* data_frame,
                           std::vector<cv::Rect>& vecicle_info);
  std::vector<LaneResult> GetSelectLaneLines() ;

  cv::Point2f GetVanishingPointByLSM(std::vector<INITLDVP>& condiate_vps);

  void RemoveVehicleRectPoint(std::vector<cv::Rect>& _inVehicleInfo,
                                             cv::Mat& PMBlackOut);
  void UpdateDataFrameParameter(DataFrame* data_frame,
                                std::vector<LaneResult>& lane_lines);
  cv::Point UpdateVanishingPoint(std::vector<LaneResult>& lane_lines,
                                 cv::Point current_vanishing_point);
  void UpdateVisualCenterPoint(std::vector<LaneResult>& _srcVecLine);

  std::vector<LaneResult> ExcludeOutLines(std::vector<LaneResult>& lane_lines);
  std::vector<LaneResult> ExcludeOutLinesByJl(std::vector<LaneResult>& lane_lines,
                                            float mScale);

  std::vector<LaneResult> ExcludeOutLinesMain(std::vector<LaneResult>& lane_lines, float mScale);

  std::vector<LaneResult> ExcludeOutLineByPoint(std::vector<LaneResult>& _srcVecLine);
 bool ExcludeOutLinesInMuliLineSingle(LaneResult& _fitline);
  bool ExcludeOutLinesInOneLine(LaneResult& _fitline);

  int GetDatumLine(std::vector<LaneResult>& lane_lines, float refer_point_x,
                   bool is_right);

  int GetSelectLine(std::vector<LaneResult>& lane_lines, bool is_right,int& offset_center);

  void TestRefineResult(std::vector<LaneResult>& line_results);
  void TestShowLineType(std::vector<LaneResult>& line_results);
};

} /* namespace rmd */

#endif
